import * as Sequelize from "sequelize";
import { DataTypes, Model /*, Optional */ } from "sequelize";
import { Base } from "./base";

export interface UserAttributes {
  id: number;
  uuid: string;
  name: string;
  nickname?: string;
  email?: string;
  salt: string;
  password: string;
  phone?: string;
  avatar?: string;
  registerIP?: string;
  createdAt: Date;
  updatedAt: Date;
  deletedAt?: Date;
}

/** *************** 定义type UserCreationAttributes 的两种方式 ******************************** */
// 第一种：直接定义CreationAttributes
export type UserCreationAttributes =
  "uuid"
  | "name"
  | "salt"
  | "password";

// 第二种：如果可选属性少，可以定义可选属性类型，再使用Optional方法得到CreationAttributes
// export type UserOptionalAttributes =
//   "id"
//   | "nickname"
//   | "email"
//   | "phone"
//   | "avatar"
//   | "registerIP"
//   | "createdAt"
//   | "updatedAt"
//   | "deletedAt";

// export type UserCreationAttributes = Optional<UserAttributes, UserOptionalAttributes>;

export class User extends Base<UserAttributes, UserCreationAttributes> implements UserAttributes {
  id: number;
  uuid: string;
  name: string;
  nickname?: string;
  email?: string;
  salt: string;
  password: string;
  phone?: string;
  avatar?: string;
  registerIP?: string;
  createdAt: Date;
  updatedAt: Date;
  deletedAt?: Date;

  static initModel (sequelize: Sequelize.Sequelize): typeof User {
    User.init({
      id: {
        autoIncrement: true,
        type: DataTypes.INTEGER.UNSIGNED,
        allowNull: false,
        primaryKey: true
      },
      uuid: {
        type: DataTypes.UUID,
        allowNull: false,
        defaultValue: Sequelize.UUIDV4,
        unique: "uuid"
      },
      name: {
        type: DataTypes.CHAR(64),
        allowNull: false,
        defaultValue: "",
        unique: "name",
        validate: {
          len: [4, 64]
        }
      },
      nickname: {
        type: DataTypes.STRING(255),
        allowNull: true
      },
      email: {
        type: DataTypes.CHAR(100),
        allowNull: true,
        unique: "email",
        validate: { isEmail: true }
      },
      salt: {
        type: DataTypes.CHAR(16),
        allowNull: false,
        defaultValue: ""
      },
      password: {
        type: DataTypes.STRING(255),
        allowNull: false,
        validate: {
          len: [6, 100]
        },
        defaultValue: "NOPASSWORD"
      },
      phone: {
        type: DataTypes.CHAR(20),
        allowNull: true,
        unique: "phone"
      },
      avatar: {
        type: DataTypes.STRING(200),
        allowNull: true
      },
      registerIP: {
        type: DataTypes.CHAR(40),
        allowNull: true,
        validate: { isIP: true }
      },
      createdAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: Sequelize.Sequelize.literal("CURRENT_TIMESTAMP")
      },
      updatedAt: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: Sequelize.Sequelize.literal("CURRENT_TIMESTAMP")
      },
      deletedAt: {
        type: DataTypes.DATE,
        allowNull: true
      }
    }, {
      sequelize,
      tableName: "User",
      timestamps: true,
      paranoid: true,
      omitNull: true,
      engine: "InnoDB",
      freezeTableName: true,
      createdAt: true,
      updatedAt: true,
      deletedAt: true,
      indexes: [
        {
          name: "PRIMARY",
          unique: true,
          using: "BTREE",
          fields: [
            { name: "id" }
          ]
        },
        {
          name: "uuid",
          unique: true,
          using: "BTREE",
          fields: [
            { name: "uuid" }
          ]
        },
        {
          name: "name",
          unique: true,
          using: "BTREE",
          fields: [
            { name: "name" }
          ]
        },
        {
          name: "email",
          unique: true,
          using: "BTREE",
          fields: [
            { name: "email" }
          ]
        },
        {
          name: "phone",
          unique: true,
          using: "BTREE",
          fields: [
            { name: "phone" }
          ]
        }
      ]
    });

    return User;
  }
}
